package control;

import java.io.File;
import java.util.ArrayList;

import ontology.EmploymentLawOntology;
import ontology.UMCourtLOntology;
import ontology.actions.general.Log;
import classes.ConfigJavaParser;
import classes.MessageTemplates;
import classes.UMCourtAgent;
import jade.content.lang.Codec;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.content.onto.basic.Action;
import jade.core.Agent;
import jade.wrapper.*;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.lang.acl.ACLMessage;

public class FaultManager extends UMCourtAgent {

	/**
	 * 
	 */
	//private static final long serialVersionUID = 4139367194903850114L;
	private File config;
	private String uri = "Config.xml";
	private static Agent agent;
	private long TICK = 1000;
	private ArrayList<classes.Agent> agentList = new ArrayList<classes.Agent>();
	private Codec codec = new SLCodec();
	private Ontology ontology = EmploymentLawOntology.getInstance();
	
	protected void setup() 
	{
		agent = this;
		System.out.println(getDate()+ ": "+this.getLocalName()+" agent is now running...");
		
		
		registerAgent("FaultManager");
		
		// Register language and ontology
		getContentManager().registerLanguage(codec);
		getContentManager().registerOntology(ontology);
		
		config = new File(uri);
		
		ArrayList<classes.Agent> list = new ConfigJavaParser(config.getAbsolutePath()).getConfig();
		
		//In the beggining start all agents
		for (int i=0;i<list.size();i++)
		{
			classes.Agent agent = list.get(i);
			//arg#1 - service name
			if (agent.getStart())
			{
				startAgent(agent.getName(), agent.getPath(), new Object[]{agent.getService()});
				agentList.add(new classes.Agent(agent.getName(), agent.getPath(), agent.getService(), agent.getStart()));
			}
		}
		
		//LOG THE STARTING PLATFORM EVENT
		Log l = new Log();
		l.setMessage("UMCourtL Platform is now starting");
		l.setTime(""+System.currentTimeMillis());
		
		System.out.println(l);
		ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
		msg.setLanguage(codec.getName());
		msg.setOntology(ontology.getName());
		try 
		{
			getContentManager().fillContent(msg, new Action(aids.DATABASE, l));
			msg.addReceiver(aids.DATABASE);
			send(msg);
		}
		catch (Exception ex) { ex.printStackTrace(); }
	    
		this.addBehaviour(new FaultCheckBehaviour(agent));
	}
	
	/**
	 * @param name The name of the agent to be started.
	 * @param path The path of the agent (e.g. package.ClassName)
	 * @param args A list of arguments to be passed to the agent
	 */
	private void startAgent(String name, String path, Object[] args)
	{
		try 
	    {
			PlatformController container = getContainerController(); 
			container.createNewAgent(name, path, args).start();
		} 
	    catch (Exception any) 
	    {
			any.printStackTrace();
		}
	}
	
	
	//Behaviours
    class FaultCheckBehaviour extends TickerBehaviour 
    {

		public FaultCheckBehaviour(Agent a) 
        {super(a, TICK);}

		@Override
		protected void onTick() 
		{
			ACLMessage msg= receive();
            if (msg!=null)
            {
            	System.out.println(msg.toString());
            }
            
			SearchConstraints sc = new SearchConstraints();
			sc.setMaxResults(new Long(50));
			
			PlatformController container = getContainerController();
			classes.Agent ag;
			
			for (int i=0;i<agentList.size();i++)
			{
				ag = agentList.get(i);
				String name = ag.getName();
				container = getContainerController();
				
				//if (name.equals(result[j].getName().getLocalName()))
				try 
				{
					container.getAgent(name);
				} 
				catch (ControllerException e) 
				{
					System.out.println("Agent "+name+" is not running... Restarting!");
					startAgent(name, ag.getPath(), new Object[]{ag.getService()});
					msg = msn.generateLogMessage("Agent "+name+" has been restarted.");
				    agent.send(msg);
				}
			}
		}
     } // end FaultCheckBehaviour
	
    

}
